package com.iiifi.kite.ip2region.impl;

import java.io.IOException;
import java.io.InputStream;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.util.StreamUtils;

import com.iiifi.kite.core.util.Exceptions;
import com.iiifi.kite.ip2region.core.DbConfig;
import com.iiifi.kite.ip2region.core.DbSearcher;
import com.iiifi.kite.ip2region.core.Ip2regionSearcher;
import com.iiifi.kite.ip2region.core.IpInfo;
import com.iiifi.kite.ip2region.properties.Ip2regionProperties;
import com.iiifi.kite.ip2region.utils.IpInfoUtil;

import lombok.RequiredArgsConstructor;

/**
 * ip2region 初始化
 *
 * @author kite@iiifi.com 花朝
 */
@RequiredArgsConstructor
public class Ip2regionSearcherImpl implements InitializingBean, Ip2regionSearcher {
    private final ResourceLoader resourceLoader;
    private final Ip2regionProperties properties;
    private DbSearcher searcher;

    @Override
    public void reload() throws Exception {
        DbConfig config = new DbConfig();
        Resource resource = resourceLoader.getResource(properties.getDbFileLocation());
        try (InputStream inputStream = resource.getInputStream()) {
            this.searcher = new DbSearcher(config, new ByteArrayDBReader(StreamUtils.copyToByteArray(inputStream)));
        }
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        reload();
    }

    @Override
    public IpInfo memorySearch(long ip) {
        try {
            return IpInfoUtil.toIpInfo(searcher.memorySearch(ip));
        } catch (IOException e) {
            throw Exceptions.unchecked(e);
        }
    }

    @Override
    public IpInfo memorySearch(String ip) {
        try {
            return IpInfoUtil.toIpInfo(searcher.memorySearch(ip));
        } catch (IOException e) {
            throw Exceptions.unchecked(e);
        }
    }

    @Override
    public IpInfo getByIndexPtr(long ptr) {
        try {
            return IpInfoUtil.toIpInfo(searcher.getByIndexPtr(ptr));
        } catch (IOException e) {
            throw Exceptions.unchecked(e);
        }
    }

    @Override
    public IpInfo btreeSearch(long ip) {
        try {
            return IpInfoUtil.toIpInfo(searcher.btreeSearch(ip));
        } catch (IOException e) {
            throw Exceptions.unchecked(e);
        }
    }

    @Override
    public IpInfo btreeSearch(String ip) {
        try {
            return IpInfoUtil.toIpInfo(searcher.btreeSearch(ip));
        } catch (IOException e) {
            throw Exceptions.unchecked(e);
        }
    }

    @Override
    public IpInfo binarySearch(long ip) {
        try {
            return IpInfoUtil.toIpInfo(searcher.binarySearch(ip));
        } catch (IOException e) {
            throw Exceptions.unchecked(e);
        }
    }

    @Override
    public IpInfo binarySearch(String ip) {
        try {
            return IpInfoUtil.toIpInfo(searcher.binarySearch(ip));
        } catch (IOException e) {
            throw Exceptions.unchecked(e);
        }
    }

}
